package com.helint.transfer.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;

@Slf4j
public class BigDataScoreClient{
	//<Request clientID="YOURID" pboc="false" mobHeader="135" password="YOURPASSWORD" serviceCode="101" idCard="92dab2cebba218980c4284d9e24e2f1f" mobile="9ae7a46554beba7f0e5107a5ce8b8357" />

	//test load balance
	private static String URL = "https://123.206.4.95:8000/BigDataScore/GetScore";
	
	//production load balance
	//	private static final String URL = "https://123.206.4.118:8000/BigDataScore/GetScore";
	
	public static void main(String[] args) throws Exception {
		

		BigDataScoreClient client = new BigDataScoreClient();
		
		String inputXMLPart1 = "<Request clientID=\"YOURID\" pboc=\"false\" mobHeader=\"135\" password=\"YOURPASSWORD\" serviceCode=\"101\" idCard=\"92dab2cebba218980c4284d9e24e2f1f\" mobile=\"";
		
		String inputXMLPart2 = "\" />";
		String mobile = null;

		String result = null, retcode = null;
		CloseableHttpClient httpClient = BigDataScoreClient.getHttpClient();
		
		mobile = getMD5("13511027652");

		String xml = inputXMLPart1 +  mobile + inputXMLPart2;
				
		try{
			
			while(true){
				
				result = client.execute(httpClient, xml);
				int index = result.indexOf("retCode=\"") + "retCode=\"".length();
				retcode = result.substring(index, index + 3);

				if("909".equals(retcode)) {
					Thread.sleep(1000);
				} else {
					break;
				}
			}
			
			log.info(result);
			
		}catch (Exception e) {
			e.printStackTrace();
		}
		
		System.out.println(result);

	}

	
	
	private static final String CHARSET = "UTF-8";
	private static final String CONTENT_TYPE_TEXT = "text/plain";
	
	private HttpPost post;
	

	public static CloseableHttpClient getHttpClient() throws Exception {

		SSLContext sslContext = SSLContexts.custom()
	            .useTLS()
	            .loadTrustMaterial(null, new TrustSelfSignedStrategy())
	            .build();

		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
	    
	    
	    Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
	            .register("https", sslsf)
	            .build();

	    //Set time out
	    SocketConfig socketConfig = SocketConfig.custom()
//                .setSoTimeout(5000)
                .build();
	    
	    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r);
	    
	    cm.setDefaultSocketConfig(socketConfig);
	    
		cm.setMaxTotal(10);
	    cm.setDefaultMaxPerRoute(10);

	    //keep alive
	    ConnectionKeepAliveStrategy keepAliveStrat = new DefaultConnectionKeepAliveStrategy() {

	        @Override
	        public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
	                long keepAlive = super.getKeepAliveDuration(response, context);
	                
	                if (keepAlive == -1) {
	                    keepAlive = 10000;
	                }
	                return keepAlive;
	        }

	    };
	    
	    CloseableHttpClient httpClient = HttpClients.custom()
	            .setConnectionManager(cm)
	            .setKeepAliveStrategy(keepAliveStrat)
	            .build();

	    //close Expired and Idle Connections
	    IdleConnectionMonitorRunnable1 monitor = new IdleConnectionMonitorRunnable1(cm);
	    Thread mt = new Thread(monitor);
	    mt.start();
	    
	    return httpClient;
	}

	public String execute(CloseableHttpClient httpClient, String reqXML) throws Exception {
		HttpResponse res = null;
		String result = null;

		post = new HttpPost(URL);
		StringEntity se = new StringEntity(reqXML,CHARSET);
		se.setContentType(CONTENT_TYPE_TEXT);
		se.setContentEncoding(CHARSET);
		post.setEntity(se);

		res = httpClient.execute(post);
		
		if (res.getStatusLine().getStatusCode() == 200) {

			//process result
			HttpEntity entity = res.getEntity();
			result = EntityUtils.toString(entity);
			if (entity != null) {
				InputStream instream = entity.getContent();
				instream.close();
			}
		}
		else{
			result = "HTTP returns: " + res.getStatusLine().getStatusCode() + res.getStatusLine().getReasonPhrase();
		}

		return result;
	}
	
	
	public void abort() {
		this.post.abort();
	}
	
	
	
	public static String getMD5(String inputString) {

		try{
			MessageDigest m = MessageDigest.getInstance("MD5");
			m.reset();
			m.update(inputString.getBytes("UTF-8"));
			byte[] digest = m.digest();
			BigInteger bigInt = new BigInteger(1,digest);
			String hashtext = bigInt.toString(16);
	
			while (hashtext.length() < 32) {
	            hashtext = "0" + hashtext;
	        }
			 
			return hashtext;
			
		}catch(Exception e) {
			return null;
		}
	}
	
    public void setUrl(String url){
    	BigDataScoreClient.URL = url;
    }
	

}


class IdleConnectionMonitorRunnable1 implements Runnable {
    
    private final PoolingHttpClientConnectionManager connMgr;
    private volatile boolean shutdown;
    
    public IdleConnectionMonitorRunnable1(PoolingHttpClientConnectionManager connMgr) {
        super();
        this.connMgr = connMgr;
    }

    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);
                    // Close expired connections
                    connMgr.closeExpiredConnections();
                }
            }
        } catch (InterruptedException ex) {
            // terminate
        }
    }
    
    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }

}
